home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / hplip / ui4 / devmgr5.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  59.4 KB  |  1,677 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import sys
  5. import time
  6. import os
  7. import gzip
  8. import select
  9. import struct
  10. from base.g import *
  11. from base import device, utils, pml, maint, models
  12. from prnt import cups
  13. from base.codes import *
  14. from ui_utils import *
  15. from PyQt4.QtCore import *
  16. from PyQt4.QtGui import *
  17. import dbus
  18. from dbus.mainloop.qt import DBusQtMainLoop
  19. from dbus import lowlevel
  20. from devmgr5_base import Ui_MainWindow
  21. from faxsetupdialog import FaxSetupDialog
  22. from plugindialog import PluginDialog
  23. from firmwaredialog import FirmwareDialog
  24. from aligndialog import AlignDialog
  25. from printdialog import PrintDialog
  26. from makecopiesdialog import MakeCopiesDialog
  27. from sendfaxdialog import SendFaxDialog
  28. from fabwindow import FABWindow
  29. from devicesetupdialog import DeviceSetupDialog
  30. from printtestpagedialog import PrintTestPageDialog
  31. from infodialog import InfoDialog
  32. from cleandialog import CleanDialog
  33. from colorcaldialog import ColorCalDialog
  34. from linefeedcaldialog import LineFeedCalDialog
  35. from pqdiagdialog import PQDiagDialog
  36. from nodevicesdialog import NoDevicesDialog
  37. from aboutdialog import AboutDialog
  38. from settingsdialog import SettingsDialog
  39. from printsettingstoolbox import PrintSettingsToolbox
  40. MIN_AUTO_REFRESH_RATE = 5
  41. MAX_AUTO_REFRESH_RATE = 60
  42. DEF_AUTO_REFRESH_RATE = 30
  43. device_list = { }
  44. model_obj = models.ModelData()
  45.  
  46. class FuncViewItem(QListWidgetItem):
  47.     
  48.     def __init__(self, parent, text, pixmap, tooltip_text, cmd):
  49.         QListWidgetItem.__init__(self, QIcon(pixmap), text, parent)
  50.         self.tooltip_text = tooltip_text
  51.         self.cmd = cmd
  52.  
  53.  
  54.  
  55. class DeviceViewItem(QListWidgetItem):
  56.     
  57.     def __init__(self, parent, text, pixmap, device_uri, is_avail = True):
  58.         QListWidgetItem.__init__(self, QIcon(pixmap), text, parent)
  59.         self.device_uri = device_uri
  60.         self.is_avail = is_avail
  61.         self.setTextAlignment(Qt.AlignHCenter)
  62.  
  63.  
  64.  
  65. class PluginInstall(QObject):
  66.     
  67.     def __init__(self, parent, plugin_type, plugin_installed):
  68.         self.parent = parent
  69.         self.plugin_type = plugin_type
  70.         self.plugin_installed = plugin_installed
  71.  
  72.     
  73.     def exec_(self):
  74.         install_plugin = True
  75.         if self.plugin_installed:
  76.             i = QMessageBox.warning(self.parent, self.parent.windowTitle(), self._PluginInstall__tr('<b>The HPLIP plugin is already installed.</b><p>Do you want to continue and re-install it?'), QMessageBox.Yes, QMessageBox.No, QMessageBox.NoButton)
  77.             install_plugin = i == QMessageBox.Yes
  78.         
  79.         if install_plugin:
  80.             su_sudo_str = su_sudo()
  81.             if su_sudo_str is None:
  82.                 QMessageBox.critical(self.parent, self.parent.windowTitle(), self._PluginInstall__tr('<b>Unable to find an appropriate su/sudo utility to run hp-plugin.</b>'), QMessageBox.Ok, QMessageBox.NoButton, QMessageBox.NoButton)
  83.             elif utils.which('hp-plugin'):
  84.                 cmd = su_sudo_str % 'hp-plugin'
  85.             else:
  86.                 cmd = su_sudo_str % 'python ./plugin.py'
  87.             log.debug(cmd)
  88.             utils.run(cmd, log_output = True, password_func = None, timeout = 1)
  89.         
  90.  
  91.     
  92.     def __tr(self, s, c = None):
  93.         return qApp.translate('DevMgr5', s, c)
  94.  
  95.  
  96.  
  97. class DevMgr5(QMainWindow, Ui_MainWindow):
  98.     
  99.     def __init__(self, toolbox_version, initial_device_uri = None, dbus_loop = None, parent = None, name = None, fl = 0):
  100.         QMainWindow.__init__(self, parent)
  101.         log.debug('Initializing toolbox UI (Qt4)...')
  102.         log.debug('HPLIP Version: %s' % prop.installed_version)
  103.         self.setupUi(self)
  104.         self.toolbox_version = toolbox_version
  105.         self.initial_device_uri = initial_device_uri
  106.         self.device_vars = { }
  107.         self.num_devices = 0
  108.         self.cur_device = None
  109.         self.cur_printer = None
  110.         self.updating = False
  111.         self.init_failed = False
  112.         self.service = None
  113.         self.user_settings = UserSettings()
  114.         self.user_settings.load()
  115.         self.user_settings.debug()
  116.         self.cur_device_uri = self.user_settings.last_used_device_uri
  117.         self.initDBus()
  118.         self.initPixmaps()
  119.         self.initMisc()
  120.         self.initUI()
  121.         cups.setPasswordCallback(showPasswordUI)
  122.         if not prop.doc_build:
  123.             self.ContentsAction.setEnabled(False)
  124.         
  125.         self.allow_auto_refresh = True
  126.         QTimer.singleShot(0, self.initalUpdate)
  127.  
  128.     
  129.     def initDBus(self):
  130.         self.dbus_loop = DBusQtMainLoop(set_as_default = True)
  131.         (self.dbus_avail, self.service, self.session_bus) = device.init_dbus(self.dbus_loop)
  132.         if not self.dbus_avail:
  133.             log.error('dBus initialization error. Exiting.')
  134.             self.init_failed = True
  135.             return None
  136.         self.session_bus.add_signal_receiver(self.handleSessionSignal, sender_keyword = 'sender', destination_keyword = 'dest', interface_keyword = 'interface', member_keyword = 'member', path_keyword = 'path')
  137.  
  138.     
  139.     def initPixmaps(self):
  140.         self.func_icons_cached = False
  141.         self.func_icons = { }
  142.         self.device_icons = { }
  143.         self.setWindowIcon(QIcon(load_pixmap('prog', '48x48')))
  144.         self.fax_icon = load_pixmap('fax2', 'other')
  145.  
  146.     
  147.     def initUI(self):
  148.         self.DeviceList.setSortingEnabled(True)
  149.         self.DeviceRefreshAction.setIcon(QIcon(load_pixmap('refresh1', '16x16')))
  150.         self.connect(self.DeviceRefreshAction, SIGNAL('triggered()'), self.DeviceRefreshAction_activated)
  151.         self.RefreshAllAction.setIcon(QIcon(load_pixmap('refresh', '16x16')))
  152.         self.connect(self.RefreshAllAction, SIGNAL('triggered()'), self.RefreshAllAction_activated)
  153.         self.SetupDeviceAction.setIcon(QIcon(load_pixmap('list_add', '16x16')))
  154.         self.connect(self.SetupDeviceAction, SIGNAL('triggered()'), self.SetupDeviceAction_activated)
  155.         self.RemoveDeviceAction.setIcon(QIcon(load_pixmap('list_remove', '16x16')))
  156.         self.connect(self.RemoveDeviceAction, SIGNAL('triggered()'), self.RemoveDeviceAction_activated)
  157.         self.PreferencesAction.setIcon(QIcon(load_pixmap('settings', '16x16')))
  158.         self.connect(self.PreferencesAction, SIGNAL('triggered()'), self.PreferencesAction_activated)
  159.         self.ContentsAction.setIcon(QIcon(load_pixmap('help', '16x16')))
  160.         self.connect(self.ContentsAction, SIGNAL('triggered()'), self.helpContents)
  161.         self.QuitAction.setIcon(QIcon(load_pixmap('quit', '16x16')))
  162.         self.connect(self.QuitAction, SIGNAL('triggered()'), self.quit)
  163.         self.connect(self.AboutAction, SIGNAL('triggered()'), self.helpAbout)
  164.         self.initActionsTab()
  165.         self.initStatusTab()
  166.         self.initSuppliesTab()
  167.         self.initPrintSettingsTab()
  168.         self.initPrintControlTab()
  169.         self.connect(self.Tabs, SIGNAL('currentChanged(int)'), self.Tabs_currentChanged)
  170.         self.splitter.setSizes([
  171.             80,
  172.             600])
  173.         self.DeviceList.setIconSize(QSize(60, 60))
  174.         self.connect(self.DeviceList, SIGNAL('currentItemChanged(QListWidgetItem * ,QListWidgetItem *)'), self.DeviceList_currentChanged)
  175.  
  176.     
  177.     def initMisc(self):
  178.         self.TabIndex = {
  179.             0: self.updateActionsTab,
  180.             1: self.updateStatusTab,
  181.             2: self.updateSuppliesTab,
  182.             3: self.updatePrintSettingsTab,
  183.             4: self.updatePrintControlTab }
  184.         self.docs = 'http://hplip.sf.net'
  185.         if prop.doc_build:
  186.             g = os.path.join(sys_conf.get('dirs', 'doc'), 'index.html')
  187.             if os.path.exists(g):
  188.                 self.docs = 'file://%s' % g
  189.             
  190.         
  191.         self.support = 'https://launchpad.net/hplip'
  192.  
  193.     
  194.     def initalUpdate(self):
  195.         if self.init_failed:
  196.             self.close()
  197.             return None
  198.         self.rescanDevices()
  199.         cont = True
  200.         if self.initial_device_uri is not None:
  201.             if not self.activateDevice(self.initial_device_uri):
  202.                 log.error('Device %s not found' % self.initial_device_uri)
  203.                 cont = False
  204.             
  205.         
  206.         if self.cur_printer:
  207.             self.getPrinterState()
  208.             if self.printer_state == cups.IPP_PRINTER_STATE_STOPPED:
  209.                 self.cur_device.sendEvent(EVENT_PRINTER_QUEUE_STOPPED, self.cur_printer)
  210.             
  211.             if not self.printer_accepting:
  212.                 self.cur_device.sendEvent(EVENT_PRINTER_QUEUE_REJECTING_JOBS, self.cur_printer)
  213.             
  214.         
  215.  
  216.     
  217.     def activateDevice(self, device_uri):
  218.         log.debug(log.bold('Activate: %s %s %s' % ('********************', device_uri, '********************')))
  219.         index = 0
  220.         d = self.DeviceList.item(index)
  221.         found = False
  222.         while d is not None:
  223.             if d.device_uri == device_uri:
  224.                 found = True
  225.                 self.DeviceList.setSelected(d, True)
  226.                 self.DeviceList.setCurrentItem(d)
  227.                 break
  228.             
  229.             index += 1
  230.             d = self.DeviceList.item(index)
  231.         return found
  232.  
  233.     
  234.     def handleSessionSignal(self, *args, **kwds):
  235.         if kwds['interface'] == 'com.hplip.Toolbox' and kwds['member'] == 'Event':
  236.             log.debug('Handling event...')
  237.             event = device.Event(*args[:6])
  238.             event.debug()
  239.             if event.event_code < EVENT_MIN_USER_EVENT:
  240.                 pass
  241.             elif event.event_code == EVENT_DEVICE_UPDATE_REPLY:
  242.                 log.debug('EVENT_DEVICE_UPDATE_REPLY (%s)' % event.device_uri)
  243.                 dev = self.findDeviceByURI(event.device_uri)
  244.                 if dev is not None:
  245.                     
  246.                     try:
  247.                         self.service.GetStatus(event.device_uri, reply_handler = self.handleStatusReply, error_handler = self.handleStatusError)
  248.                     except dbus.exceptions.DBusException:
  249.                         e = None
  250.                         log.error('dbus call to GetStatus() failed.')
  251.                     except:
  252.                         None<EXCEPTION MATCH>dbus.exceptions.DBusException
  253.                     
  254.  
  255.                 None<EXCEPTION MATCH>dbus.exceptions.DBusException
  256.             elif event.event_code == EVENT_USER_CONFIGURATION_CHANGED:
  257.                 log.debug('EVENT_USER_CONFIGURATION_CHANGED')
  258.                 self.user_settings.load()
  259.             elif event.event_code == EVENT_HISTORY_UPDATE:
  260.                 log.debug('EVENT_HISTORY_UPDATE (%s)' % event.device_uri)
  261.                 dev = self.findDeviceByURI(event.device_uri)
  262.                 if dev is not None:
  263.                     self.updateHistory(dev)
  264.                 
  265.             elif event.event_code == EVENT_SYSTEMTRAY_EXIT:
  266.                 log.debug('EVENT_SYSTEMTRAY_EXIT')
  267.                 log.error('HPLIP Status Service was closed. HPLIP Device Manager will now exit.')
  268.                 self.close()
  269.             elif event.event_code == EVENT_RAISE_DEVICE_MANAGER:
  270.                 log.debug('EVENT_RAISE_DEVICE_MANAGER')
  271.                 self.showNormal()
  272.                 self.setWindowState(self.windowState() & ~(Qt.WindowMinimized) | Qt.WindowActive)
  273.                 self.raise_()
  274.             elif event.event_code in (EVENT_DEVICE_START_POLLING, EVENT_DEVICE_STOP_POLLING, EVENT_POLLING_REQUEST):
  275.                 pass
  276.             else:
  277.                 log.error('Unhandled event: %d' % event.event_code)
  278.         
  279.  
  280.     
  281.     def handleStatusReply(self, device_uri, data):
  282.         dev = self.findDeviceByURI(device_uri)
  283.         if dev is not None:
  284.             t = { }
  285.             for key in data:
  286.                 value = model_obj.convert_data(str(key), str(data[key]))
  287.                 t.setdefault(key, value)
  288.             
  289.             dev.dq = t.copy()
  290.             for d in dev.dq:
  291.                 dev.__dict__[d.replace('-', '_')] = dev.dq[d]
  292.             
  293.             self.updateDevice(dev)
  294.         
  295.  
  296.     
  297.     def handleStatusError(self, e):
  298.         log.error(str(e))
  299.  
  300.     
  301.     def updateHistory(self, dev = None):
  302.         if dev is None:
  303.             dev = self.cur_device
  304.         
  305.         
  306.         try:
  307.             self.service.GetHistory(dev.device_uri, reply_handler = self.handleHistoryReply, error_handler = self.handleHistoryError)
  308.         except dbus.exceptions.DBusException:
  309.             e = None
  310.             log.error('dbus call to GetHistory() failed.')
  311.  
  312.  
  313.     
  314.     def handleHistoryReply(self, device_uri, history):
  315.         dev = self.findDeviceByURI(device_uri)
  316.         if dev is not None:
  317.             result = []
  318.             history.reverse()
  319.             for h in history:
  320.                 result.append(device.Event(*tuple(h)))
  321.             
  322.             
  323.             try:
  324.                 self.error_code = result[0].event_code
  325.             except IndexError:
  326.                 self.error_code = STATUS_UNKNOWN
  327.  
  328.             dev.error_state = STATUS_TO_ERROR_STATE_MAP.get(self.error_code, ERROR_STATE_CLEAR)
  329.             dev.hist = result
  330.             self.updateDevice(dev)
  331.         
  332.  
  333.     
  334.     def handleHistoryError(self, e):
  335.         log.error(str(e))
  336.  
  337.     
  338.     def sendMessage(self, device_uri, printer_name, event_code, username = prop.username, job_id = 0, title = ''):
  339.         device.Event(device_uri, printer_name, event_code, username, job_id, title).send_via_dbus(self.session_bus)
  340.  
  341.     
  342.     def timedRefresh(self):
  343.         if not (self.updating) and self.user_settings.auto_refresh and self.allow_auto_refresh:
  344.             log.debug('Refresh timer...')
  345.             self.cleanupChildren()
  346.             if self.user_settings.auto_refresh_type == 0:
  347.                 self.requestDeviceUpdate()
  348.             else:
  349.                 self.rescanDevices()
  350.         
  351.  
  352.     
  353.     def Tabs_currentChanged(self, tab = 0):
  354.         ''' Called when the active tab changes.
  355.             Update newly displayed tab.
  356.         '''
  357.         if self.cur_device is not None:
  358.             self.TabIndex[tab]()
  359.         
  360.  
  361.     
  362.     def updateAllTabs(self):
  363.         for tab in self.TabIndex:
  364.             self.TabIndex[tab]()
  365.         
  366.  
  367.     
  368.     def updateCurrentTab(self):
  369.         log.debug('updateCurrentTab()')
  370.         self.TabIndex[self.Tabs.currentIndex()]()
  371.  
  372.     
  373.     def DeviceRefreshAction_activated(self):
  374.         self.DeviceRefreshAction.setEnabled(False)
  375.         self.requestDeviceUpdate()
  376.         self.DeviceRefreshAction.setEnabled(True)
  377.  
  378.     
  379.     def RefreshAllAction_activated(self):
  380.         self.rescanDevices()
  381.  
  382.     
  383.     def createDeviceIcon(self, dev = None):
  384.         if dev is None:
  385.             dev = self.cur_device
  386.         
  387.         
  388.         try:
  389.             dev.icon
  390.         except AttributeError:
  391.             dev.icon = 'default_printer'
  392.  
  393.         
  394.         try:
  395.             self.device_icons[dev.icon]
  396.         except:
  397.             self.device_icons[dev.icon] = load_pixmap(dev.icon, 'devices')
  398.  
  399.         pix = self.device_icons[dev.icon]
  400.         w = pix.width()
  401.         h = pix.height()
  402.         error_state = dev.error_state
  403.         icon = QPixmap(w, h)
  404.         p = QPainter(icon)
  405.         p.eraseRect(0, 0, icon.width(), icon.height())
  406.         p.drawPixmap(0, 0, pix)
  407.         
  408.         try:
  409.             tech_type = dev.tech_type
  410.         except AttributeError:
  411.             tech_type = TECH_TYPE_NONE
  412.  
  413.         if dev.device_type == DEVICE_TYPE_FAX:
  414.             p.drawPixmap(w - self.fax_icon.width(), 0, self.fax_icon)
  415.         
  416.         if error_state != ERROR_STATE_CLEAR:
  417.             if tech_type in (TECH_TYPE_COLOR_INK, TECH_TYPE_MONO_INK):
  418.                 status_icon = getStatusOverlayIcon(error_state)[0]
  419.             else:
  420.                 status_icon = getStatusOverlayIcon(error_state)[1]
  421.             if status_icon is not None:
  422.                 p.drawPixmap(0, 0, status_icon)
  423.             
  424.         
  425.         p.end()
  426.         return icon
  427.  
  428.     
  429.     def refreshDeviceList(self):
  430.         log.debug('Rescanning device list...')
  431.         beginWaitCursor()
  432.         self.updating = True
  433.         self.setWindowTitle(self._DevMgr5__tr('Refreshing Device List - HP Device Manager'))
  434.         self.statusBar().showMessage(self._DevMgr5__tr('Refreshing device list...'))
  435.         self.cups_devices = device.getSupportedCUPSDevices([
  436.             'hp',
  437.             'hpfax'])
  438.         current = None
  439.         
  440.         try:
  441.             adds = []
  442.             for d in self.cups_devices:
  443.                 if d not in device_list:
  444.                     adds.append(d)
  445.                     continue
  446.             
  447.             log.debug('Adds: %s' % ','.join(adds))
  448.             removals = []
  449.             for d in device_list:
  450.                 if d not in self.cups_devices:
  451.                     removals.append(d)
  452.                     continue
  453.             
  454.             log.debug('Removals (1): %s' % ','.join(removals))
  455.             updates = []
  456.             for d in device_list:
  457.                 if d not in adds and d not in removals:
  458.                     updates.append(d)
  459.                     continue
  460.             
  461.             log.debug('Updates: %s' % ','.join(updates))
  462.             for d in adds:
  463.                 log.debug('adding: %s' % d)
  464.                 dev = device.Device(d, service = self.service, disable_dbus = False)
  465.                 if not dev.supported:
  466.                     log.debug('Unsupported model - removing device.')
  467.                     removals.append(d)
  468.                     continue
  469.                 
  470.                 icon = self.createDeviceIcon(dev)
  471.                 if dev.device_type == DEVICE_TYPE_FAX:
  472.                     DeviceViewItem(self.DeviceList, self._DevMgr5__tr('%1 (Fax)').arg(dev.model_ui), icon, d)
  473.                 elif dev.fax_type:
  474.                     DeviceViewItem(self.DeviceList, self._DevMgr5__tr('%1 (Printer)').arg(dev.model_ui), icon, d)
  475.                 else:
  476.                     DeviceViewItem(self.DeviceList, dev.model_ui, icon, d)
  477.                 device_list[d] = dev
  478.             
  479.             log.debug('Removals (2): %s' % ','.join(removals))
  480.             for d in removals:
  481.                 index = self.DeviceList.count() - 1
  482.                 item = self.DeviceList.item(index)
  483.                 log.debug('removing: %s' % d)
  484.                 
  485.                 try:
  486.                     del device_list[d]
  487.                 except KeyError:
  488.                     pass
  489.  
  490.                 while index >= 0 and item is not None:
  491.                     if item.device_uri == d:
  492.                         self.DeviceList.takeItem(index)
  493.                         break
  494.                     
  495.                     index -= 1
  496.                     item = self.DeviceList.item(index)
  497.                 qApp.processEvents()
  498.             
  499.             self.DeviceList.updateGeometry()
  500.             qApp.processEvents()
  501.             if len(device_list):
  502.                 for tab in self.TabIndex:
  503.                     self.Tabs.setTabEnabled(tab, True)
  504.                 
  505.                 if self.cur_device_uri:
  506.                     index = 0
  507.                     item = first_item = self.DeviceList.item(index)
  508.                     while item is not None:
  509.                         qApp.processEvents()
  510.                         if item.device_uri == self.cur_device_uri:
  511.                             current = item
  512.                             self.statusBar().showMessage(self.cur_device_uri)
  513.                             break
  514.                         
  515.                         index += 1
  516.                         item = self.DeviceList.item(index)
  517.                     self.cur_device = None
  518.                     self.cur_device_uri = ''
  519.                 
  520.                 if self.cur_device is None:
  521.                     i = self.DeviceList.item(0)
  522.                     if i is not None:
  523.                         self.cur_device_uri = i.device_uri
  524.                         self.cur_device = device_list[self.cur_device_uri]
  525.                         current = i
  526.                     
  527.                 
  528.                 self.updatePrinterCombos()
  529.                 if self.cur_device_uri:
  530.                     user_conf.set('last_used', 'device_uri', self.cur_device_uri)
  531.                 
  532.                 for d in updates + adds:
  533.                     if d not in removals:
  534.                         self.requestDeviceUpdate(device_list[d])
  535.                         continue
  536.                 
  537.             else:
  538.                 self.cur_device = None
  539.                 self.DeviceRefreshAction.setEnabled(False)
  540.                 self.RemoveDeviceAction.setEnabled(False)
  541.                 self.updating = False
  542.                 self.statusBar().showMessage(self._DevMgr5__tr('Press F6 to refresh.'))
  543.                 for tab in self.TabIndex:
  544.                     self.Tabs.setTabEnabled(tab, False)
  545.                 
  546.                 endWaitCursor()
  547.                 dlg = NoDevicesDialog(self)
  548.                 dlg.exec_()
  549.         finally:
  550.             self.updating = False
  551.             endWaitCursor()
  552.  
  553.         if current is not None:
  554.             self.DeviceList.setCurrentItem(current)
  555.         
  556.         self.DeviceRefreshAction.setEnabled(True)
  557.         if self.cur_device is not None:
  558.             self.RemoveDeviceAction.setEnabled(True)
  559.             self.statusBar().showMessage(self.cur_device_uri)
  560.             self.updateWindowTitle()
  561.         
  562.  
  563.     
  564.     def updateWindowTitle(self):
  565.         if self.cur_device.device_type == DEVICE_TYPE_FAX:
  566.             self.setWindowTitle(self._DevMgr5__tr('HP Device Manager - %1 (Fax)').arg(self.cur_device.model_ui))
  567.         elif self.cur_device.fax_type:
  568.             self.setWindowTitle(self._DevMgr5__tr('HP Device Manager - %1 (Printer)').arg(self.cur_device.model_ui))
  569.         else:
  570.             self.setWindowTitle(self._DevMgr5__tr('HP Device Manager - %1').arg(self.cur_device.model_ui))
  571.         self.statusBar().showMessage(self.cur_device_uri)
  572.  
  573.     
  574.     def updateDeviceByURI(self, device_uri):
  575.         return self.updateDevice(self.findDeviceByURI(device_uri))
  576.  
  577.     
  578.     def updateDevice(self, dev = None, update_tab = True):
  579.         ''' Update the device icon and currently displayed tab.
  580.         '''
  581.         if dev is None:
  582.             dev = self.cur_device
  583.         
  584.         log.debug('updateDevice(%s)' % dev.device_uri)
  585.         item = self.findItem(dev)
  586.         if item is not None:
  587.             item.setIcon(QIcon(self.createDeviceIcon(dev)))
  588.         
  589.         if dev is self.cur_device and update_tab:
  590.             self.updatePrinterCombos()
  591.             self.updateCurrentTab()
  592.             self.statusBar().showMessage(self.cur_device_uri)
  593.         
  594.  
  595.     
  596.     def DeviceList_currentChanged(self, i, j):
  597.         if i is not None and not (self.updating):
  598.             self.cur_device_uri = self.DeviceList.currentItem().device_uri
  599.             self.cur_device = device_list[self.cur_device_uri]
  600.             user_conf.set('last_used', 'device_uri', self.cur_device_uri)
  601.             self.updateDevice()
  602.             self.updateWindowTitle()
  603.         
  604.  
  605.     
  606.     def findItem(self, dev):
  607.         if dev is None:
  608.             dev = self.cur_device
  609.         
  610.         return self.findItemByURI(dev.device_uri)
  611.  
  612.     
  613.     def findItemByURI(self, device_uri):
  614.         index = 0
  615.         item = self.DeviceList.item(index)
  616.         while item is not None:
  617.             if item.device_uri == device_uri:
  618.                 return item
  619.             index += 1
  620.             item = self.DeviceList.item(index)
  621.             continue
  622.             item.device_uri == device_uri
  623.  
  624.     
  625.     def findDeviceByURI(self, device_uri):
  626.         
  627.         try:
  628.             return device_list[device_uri]
  629.         except:
  630.             return None
  631.  
  632.  
  633.     
  634.     def requestDeviceUpdate(self, dev = None, item = None):
  635.         ''' Submit device update request to update thread. '''
  636.         if dev is None:
  637.             dev = self.cur_device
  638.         
  639.         if dev is not None:
  640.             dev.error_state = ERROR_STATE_REFRESHING
  641.             self.updateDevice(dev, update_tab = False)
  642.             self.sendMessage(dev.device_uri, '', EVENT_DEVICE_UPDATE_REQUESTED)
  643.         
  644.  
  645.     
  646.     def rescanDevices(self):
  647.         ''' Rescan and update all devices. '''
  648.         if not self.updating:
  649.             self.RefreshAllAction.setEnabled(False)
  650.             
  651.             try:
  652.                 self.refreshDeviceList()
  653.             finally:
  654.                 self.RefreshAllAction.setEnabled(True)
  655.  
  656.         
  657.  
  658.     
  659.     def callback(self):
  660.         qApp.processEvents()
  661.  
  662.     
  663.     def DeviceList_rightButtonClicked(self, item, pos):
  664.         popup = QPopupMenu(self)
  665.         if item is not None and item is self.DeviceList.currentItem():
  666.             if self.cur_device.error_state != ERROR_STATE_ERROR:
  667.                 if self.cur_device.device_type == DEVICE_TYPE_PRINTER:
  668.                     popup.insertItem(self._DevMgr5__tr('Print...'), self.PrintButton_clicked)
  669.                     if self.cur_device.scan_type:
  670.                         popup.insertItem(self._DevMgr5__tr('Scan...'), self.ScanButton_clicked)
  671.                     
  672.                     if self.cur_device.pcard_type:
  673.                         popup.insertItem(self._DevMgr5__tr('Access Photo Cards...'), self.PCardButton_clicked)
  674.                     
  675.                     if self.cur_device.copy_type:
  676.                         popup.insertItem(self._DevMgr5__tr('Make Copies...'), self.MakeCopiesButton_clicked)
  677.                     
  678.                 elif self.cur_device.device_type == DEVICE_TYPE_FAX:
  679.                     if self.cur_device.fax_type:
  680.                         popup.insertItem(self._DevMgr5__tr('Send Fax...'), self.SendFaxButton_clicked)
  681.                     
  682.                 
  683.                 popup.insertSeparator()
  684.             
  685.             if not self.updating:
  686.                 popup.insertItem(self._DevMgr5__tr('Refresh Device'), self.DeviceRefreshAction_activated)
  687.             
  688.         
  689.         if not self.updating:
  690.             popup.insertItem(self._DevMgr5__tr('Refresh All'), self.RefreshAllAction_activated)
  691.         
  692.         popup.popup(pos)
  693.  
  694.     
  695.     def updatePrinterCombos(self):
  696.         self.PrintSettingsPrinterNameCombo.clear()
  697.         self.PrintControlPrinterNameCombo.clear()
  698.         if self.cur_device is not None and self.cur_device.supported:
  699.             for c in self.cur_device.cups_printers:
  700.                 self.PrintSettingsPrinterNameCombo.insertItem(0, c.decode('utf-8'))
  701.                 self.PrintControlPrinterNameCombo.insertItem(0, c.decode('utf-8'))
  702.             
  703.             self.cur_printer = unicode(self.PrintSettingsPrinterNameCombo.currentText())
  704.         
  705.  
  706.     
  707.     def PrintSettingsPrinterNameCombo_activated(self, s):
  708.         self.cur_printer = unicode(s)
  709.         self.PrintControlPrinterNameCombo.setCurrentText(self.cur_printer.encode('latin1'))
  710.         return self.PrinterCombo_activated(self.cur_printer)
  711.  
  712.     
  713.     def PrintControlPrinterNameCombo_activated(self, s):
  714.         self.cur_printer = unicode(s)
  715.         self.PrintSettingsPrinterNameCombo.setCurrentText(self.cur_printer.encode('latin1'))
  716.         return self.PrinterCombo_activated(self.cur_printer)
  717.  
  718.     
  719.     def PrinterCombo_activated(self, printer):
  720.         self.updateCurrentTab()
  721.  
  722.     
  723.     def initActionsTab(self):
  724.         self.click_lock = None
  725.         self.ActionsList.setIconSize(QSize(32, 32))
  726.         self.connect(self.ActionsList, SIGNAL('itemClicked(QListWidgetItem *)'), self.ActionsList_clicked)
  727.         self.connect(self.ActionsList, SIGNAL('itemDoubleClicked(QListWidgetItem *)'), self.ActionsList_clicked)
  728.  
  729.     
  730.     def updateActionsTab(self):
  731.         beginWaitCursor()
  732.         
  733.         try:
  734.             self.ActionsList.clear()
  735.             d = self.cur_device
  736.             if d is not None:
  737.                 if d.device_state != DEVICE_STATE_NOT_FOUND:
  738.                     pass
  739.                 avail = d.supported
  740.                 if d.fax_type and prop.fax_build and d.device_type == DEVICE_TYPE_FAX and sys.hexversion >= 33751280:
  741.                     pass
  742.                 fax = avail
  743.                 if d.device_type == DEVICE_TYPE_PRINTER:
  744.                     pass
  745.                 printer = avail
  746.                 req_plugin = d.plugin == PLUGIN_REQUIRED
  747.                 opt_plugin = d.plugin == PLUGIN_OPTIONAL
  748.                 hplip_conf = ConfigParser.ConfigParser()
  749.                 fp = open('/etc/hp/hplip.conf', 'r')
  750.                 hplip_conf.readfp(fp)
  751.                 fp.close()
  752.                 
  753.                 try:
  754.                     plugin_installed = utils.to_bool(hplip_conf.get('hplip', 'plugin'))
  755.                 except ConfigParser.NoOptionError:
  756.                     plugin_installed = False
  757.  
  758.                 if d.plugin != PLUGIN_NONE:
  759.                     if req_plugin and plugin_installed:
  760.                         x = self._DevMgr5__tr('Download and install<br>required plugin (already installed).')
  761.                     elif req_plugin and not plugin_installed:
  762.                         x = self._DevMgr5__tr('Download and install<br>required plugin (needs installation).')
  763.                     elif opt_plugin and plugin_installed:
  764.                         x = self._DevMgr5__tr('Download and install<br>optional plugin (already installed).')
  765.                     elif opt_plugin and not plugin_installed:
  766.                         x = self._DevMgr5__tr('Download and install<br>optional plugin (needs installation).')
  767.                     
  768.                 else:
  769.                     x = ''
  770.                 self.ICONS = [
  771.                     None,
  772.                     None,
  773.                     None,
  774.                     None,
  775.                     None,
  776.                     None,
  777.                     None,
  778.                     None,
  779.                     None,
  780.                     None,
  781.                     None,
  782.                     None,
  783.                     None,
  784.                     None,
  785.                     ((None, (None,), ((lambda : printer), self._DevMgr5__tr('Print'), 'print', (self._DevMgr5__tr('Print documents or files.'),), (lambda : PrintDialog(self, self.cur_printer)))), ((lambda : if d.scan_type and prop.scan_build and d.device_type == DEVICE_TYPE_PRINTER and avail:
  786. passself.user_settings.cmd_scan), self._DevMgr5__tr('Scan'), 'scan', self._DevMgr5__tr('Scan a document, image, or photograph.<br>'), self.user_settings.cmd_scan)),
  787.                     (((lambda : if d.copy_type and d.device_type == DEVICE_TYPE_PRINTER:
  788. passavail), self._DevMgr5__tr('Make Copies'), 'makecopies', (self._DevMgr5__tr('Make copies on the device controlled by the PC.<br>'),), (lambda : MakeCopiesDialog(self, self.cur_device_uri))),),
  789.                     (((((lambda : fax), self._DevMgr5__tr('Send Fax'), 'fax', (self._DevMgr5__tr('Send a fax from the PC.'),), (lambda : SendFaxDialog(self, self.cur_printer, self.cur_device_uri))),), ((lambda : fax), self._DevMgr5__tr('Fax Setup'), 'fax_setup', (self._DevMgr5__tr('Fax support must be setup before you can send faxes.'),), (lambda : FaxSetupDialog(self, self.cur_device_uri)))), ((lambda : if fax:
  790. passself.user_settings.cmd_fab), self._DevMgr5__tr('Fax Address Book'), 'fab', self._DevMgr5__tr('Setup fax phone numbers to use when sending faxes from the PC.'), self.user_settings.cmd_fab)),
  791.                     ((((lambda : if d.power_settings != POWER_SETTINGS_NONE:
  792. passavail), self._DevMgr5__tr('Device Settings'), 'settings', (self._DevMgr5__tr('Your device has special device settings.<br>You may alter these settings here.'),), (lambda : DeviceSetupDialog(self, self.cur_device_uri))),), (((((((((((lambda : printer), self._DevMgr5__tr('Print Test Page'), 'testpage', (self._DevMgr5__tr('Print a test page to test the setup of your printer.'),), (lambda : PrintTestPageDialog(self, self.cur_printer))), ((lambda : True), self._DevMgr5__tr('View Printer and Device Information'), 'cups', (self._DevMgr5__tr('View information about the device and all its CUPS queues.'),), (lambda : InfoDialog(self, self.cur_device_uri)))), ((lambda : if printer:
  793. passd.align_type != ALIGN_TYPE_NONE), self._DevMgr5__tr('Align Cartridges (Print Heads)'), 'align', (self._DevMgr5__tr('This will improve the quality of output when a new cartridge is installed.'),), (lambda : AlignDialog(self, self.cur_device_uri)))), ((lambda : if printer:
  794. passd.clean_type != CLEAN_TYPE_NONE), self._DevMgr5__tr('Clean Cartridges'), 'clean', (self._DevMgr5__tr('You only need to perform this action if you are<br>having problems with poor printout quality due to clogged ink nozzles.'),), (lambda : CleanDialog(self, self.cur_device_uri)))), ((lambda : if printer and d.color_cal_type != COLOR_CAL_TYPE_NONE:
  795. passd.color_cal_type == COLOR_CAL_TYPE_TYPHOON), self._DevMgr5__tr('Color Calibration'), 'colorcal', (self._DevMgr5__tr("Use this procedure to optimimize your printer's color output<br>(requires glossy photo paper)."),), (lambda : ColorCalDialog(self, self.cur_device_uri)))), ((lambda : if printer and d.color_cal_type != COLOR_CAL_TYPE_NONE:
  796. passd.color_cal_type != COLOR_CAL_TYPE_TYPHOON), self._DevMgr5__tr('Color Calibration'), 'colorcal', (self._DevMgr5__tr("Use this procedure to optimimize your printer's color output."),), (lambda : ColorCalDialog(self, self.cur_device_uri)))), ((lambda : if printer:
  797. passd.linefeed_cal_type != LINEFEED_CAL_TYPE_NONE), self._DevMgr5__tr('Line Feed Calibration'), 'linefeed_cal', (self._DevMgr5__tr('Use line feed calibration to optimize print quality<br>(to remove gaps in the printed output).'),), (lambda : LineFeedCalDialog(self, self.cur_device_uri)))), ((lambda : if printer:
  798. passd.pq_diag_type != PQ_DIAG_TYPE_NONE), self._DevMgr5__tr('Print Diagnostic Page'), 'pq_diag', (self._DevMgr5__tr('Your printer can print a test page <br>to help diagnose print quality problems.'),), (lambda : PQDiagDialog(self, self.cur_device_uri)))), (((lambda : if printer:
  799. passd.fw_download), self._DevMgr5__tr('Download Firmware'), 'firmware', (self._DevMgr5__tr('Download firmware to your printer <br>(required on some devices after each power-up).'),), (lambda : FirmwareDialog(self, self.cur_device_uri))),), (lambda : req_plugin), (self._DevMgr5__tr('Install Required Plugin'), 'plugin', x), (lambda : PluginInstall(self, d.plugin, plugin_installed))),), (lambda : opt_plugin), (self._DevMgr5__tr('Install Optional Plugin'), 'plugin', x), (lambda : PluginInstall(self, d.plugin, plugin_installed))),
  800.                     ((lambda : True), self._DevMgr5__tr('Visit HPLIP Support Website'), 'support2', self._DevMgr5__tr('Visit HPLIP Support Website.'), self.support),
  801.                     ((lambda : True), self._DevMgr5__tr('Help'), 'help', self._DevMgr5__tr('View HPLIP help.'), self.docs)]
  802.                 if not self.func_icons_cached:
  803.                     for filter, text, icon, tooltip, cmd in self.ICONS:
  804.                         self.func_icons[icon] = load_pixmap(icon, '32x32')
  805.                     
  806.                     self.func_icons_cached = True
  807.                 
  808.                 for filter, text, icon, tooltip, cmd in self.ICONS:
  809.                     if filter is not None:
  810.                         if not filter():
  811.                             continue
  812.                         
  813.                     
  814.                     FuncViewItem(self.ActionsList, text, self.func_icons[icon], tooltip, cmd)
  815.                 
  816.         finally:
  817.             endWaitCursor()
  818.  
  819.  
  820.     
  821.     def ActionsList_clicked(self, item):
  822.         if item is not None and self.click_lock is not item:
  823.             self.click_lock = item
  824.             if item.cmd and callable(item.cmd):
  825.                 dlg = item.cmd()
  826.                 self.sendMessage('', '', EVENT_DEVICE_STOP_POLLING)
  827.                 
  828.                 try:
  829.                     dlg.exec_()
  830.                 finally:
  831.                     self.sendMessage('', '', EVENT_DEVICE_START_POLLING)
  832.  
  833.             else:
  834.                 beginWaitCursor()
  835.                 if item.cmd.split(':')[0] in ('http', 'https', 'file'):
  836.                     log.debug('Opening browser to: %s' % item.cmd)
  837.                     utils.openURL(item.cmd)
  838.                 else:
  839.                     self.runExternalCommand(item.cmd)
  840.             QTimer.singleShot(1000, self.unlockClick)
  841.         
  842.  
  843.     
  844.     def unlockClick(self):
  845.         self.click_lock = None
  846.         endWaitCursor()
  847.  
  848.     
  849.     def ActionsList_customContextMenuRequested(self, p):
  850.         print p
  851.  
  852.     
  853.     def initStatusTab(self):
  854.         self.StatusTable.setColumnCount(0)
  855.         self.status_headers = [
  856.             self._DevMgr5__tr(''),
  857.             self._DevMgr5__tr('Status'),
  858.             self._DevMgr5__tr('Date and Time'),
  859.             self._DevMgr5__tr('Code'),
  860.             self._DevMgr5__tr('Job ID'),
  861.             self._DevMgr5__tr('Description')]
  862.  
  863.     
  864.     def updateStatusTab(self):
  865.         self.updateStatusLCD()
  866.         self.updateStatusTable()
  867.  
  868.     
  869.     def updateStatusLCD(self):
  870.         if self.cur_device is not None and self.cur_device.hist and self.cur_device.supported:
  871.             dq = self.cur_device.dq
  872.             if dq.get('panel', 0) == 1:
  873.                 line1 = dq.get('panel-line1', '')
  874.                 line2 = dq.get('panel-line2', '')
  875.             else:
  876.                 
  877.                 try:
  878.                     line1 = device.queryString(self.cur_device.hist[0].event_code)
  879.                 except (AttributeError, TypeError):
  880.                     line1 = ''
  881.  
  882.                 line2 = ''
  883.             self.drawStatusLCD(line1, line2)
  884.         elif self.cur_device.status_type == STATUS_TYPE_NONE:
  885.             self.drawStatusLCD(self._DevMgr5__tr('Status information not'), self._DevMgr5__tr('available for this device.'))
  886.         elif not self.cur_device.supported:
  887.             self.drawStatusLCD(self._DevMgr5__tr('Device not supported.'))
  888.         elif not self.cur_device.hist:
  889.             self.drawStatusLCD(self._DevMgr5__tr('No status history available.'))
  890.         else:
  891.             self.drawStatusLCD()
  892.  
  893.     
  894.     def drawStatusLCD(self, line1 = '', line2 = ''):
  895.         pm = load_pixmap('panel_lcd', 'other')
  896.         p = QPainter()
  897.         p.begin(pm)
  898.         p.setPen(QColor(0, 0, 0))
  899.         p.setFont(self.font())
  900.         (x, y_line1, y_line2) = (10, 17, 33)
  901.         if line1:
  902.             p.drawText(x, y_line1, line1)
  903.         
  904.         if line2:
  905.             p.drawText(x, y_line2, line2)
  906.         
  907.         p.end()
  908.         self.LCD.setPixmap(pm)
  909.  
  910.     
  911.     def updateStatusTable(self):
  912.         self.StatusTable.clear()
  913.         flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled
  914.         row = 0
  915.         hist = self.cur_device.hist[:]
  916.         if hist:
  917.             self.StatusTable.setRowCount(len(hist))
  918.             self.StatusTable.setColumnCount(len(self.status_headers))
  919.             self.StatusTable.setHorizontalHeaderLabels(self.status_headers)
  920.             self.StatusTable.verticalHeader().hide()
  921.             self.StatusTable.horizontalHeader().show()
  922.             hist.reverse()
  923.             row = len(hist) - 1
  924.             for e in hist:
  925.                 if e is None:
  926.                     continue
  927.                 
  928.                 ess = device.queryString(e.event_code, 0)
  929.                 esl = device.queryString(e.event_code, 1)
  930.                 if row == 0:
  931.                     desc = self._DevMgr5__tr('(most recent)')
  932.                 else:
  933.                     desc = getTimeDeltaDesc(e.timedate)
  934.                 dt = QDateTime()
  935.                 dt.setTime_t(int(e.timedate))
  936.                 tt = QString('%1 %2').arg(dt.toString()).arg(desc)
  937.                 if e.job_id:
  938.                     job_id = unicode(e.job_id)
  939.                 else:
  940.                     job_id = u''
  941.                 error_state = STATUS_TO_ERROR_STATE_MAP.get(e.event_code, ERROR_STATE_CLEAR)
  942.                 tech_type = self.cur_device.tech_type
  943.                 if tech_type in (TECH_TYPE_COLOR_INK, TECH_TYPE_MONO_INK):
  944.                     status_pix = getStatusListIcon(error_state)[0]
  945.                 else:
  946.                     status_pix = getStatusListIcon(error_state)[1]
  947.                 event_code = unicode(e.event_code)
  948.                 i = QTableWidgetItem(QIcon(status_pix), self._DevMgr5__tr(''))
  949.                 i.setFlags(flags)
  950.                 self.StatusTable.setItem(row, 0, i)
  951.                 for col, t in [
  952.                     (1, ess),
  953.                     (2, tt),
  954.                     (3, event_code),
  955.                     (4, job_id),
  956.                     (5, esl)]:
  957.                     i = QTableWidgetItem(QString(t))
  958.                     i.setFlags(flags)
  959.                     self.StatusTable.setItem(row, col, i)
  960.                 
  961.                 row -= 1
  962.             
  963.             self.StatusTable.resizeColumnsToContents()
  964.             self.StatusTable.setColumnWidth(0, 24)
  965.         else:
  966.             self.StatusTable.setRowCount(1)
  967.             self.StatusTable.setColumnCount(2)
  968.             self.StatusTable.setHorizontalHeaderLabels([
  969.                 '',
  970.                 ''])
  971.             self.StatusTable.verticalHeader().hide()
  972.             self.StatusTable.horizontalHeader().hide()
  973.             flags = Qt.ItemIsEnabled
  974.             pixmap = getStatusListIcon(ERROR_STATE_ERROR)[0]
  975.             i = QTableWidgetItem(QIcon(pixmap), self._DevMgr5__tr(''))
  976.             i.setFlags(flags)
  977.             self.StatusTable.setItem(row, 0, i)
  978.             i = QTableWidgetItem(self._DevMgr5__tr('Status information not available for this device.'))
  979.             i.setFlags(flags)
  980.             self.StatusTable.setItem(0, 1, i)
  981.             self.StatusTable.resizeColumnsToContents()
  982.             self.StatusTable.setColumnWidth(0, 24)
  983.  
  984.     
  985.     def initSuppliesTab(self):
  986.         self.pix_battery = load_pixmap('battery', '16x16')
  987.         yellow = '#ffff00'
  988.         light_yellow = '#ffffcc'
  989.         cyan = '#00ffff'
  990.         light_cyan = '#ccffff'
  991.         magenta = '#ff00ff'
  992.         light_magenta = '#ffccff'
  993.         black = '#000000'
  994.         blue = '#0000ff'
  995.         dark_grey = '#808080'
  996.         light_grey = '#c0c0c0'
  997.         self.TYPE_TO_PIX_MAP = {
  998.             AGENT_TYPE_UNSPECIFIED: [
  999.                 black],
  1000.             AGENT_TYPE_BLACK: [
  1001.                 black],
  1002.             AGENT_TYPE_CMY: [
  1003.                 cyan,
  1004.                 magenta,
  1005.                 yellow],
  1006.             AGENT_TYPE_KCM: [
  1007.                 light_cyan,
  1008.                 light_magenta,
  1009.                 light_yellow],
  1010.             AGENT_TYPE_GGK: [
  1011.                 dark_grey],
  1012.             AGENT_TYPE_YELLOW: [
  1013.                 yellow],
  1014.             AGENT_TYPE_MAGENTA: [
  1015.                 magenta],
  1016.             AGENT_TYPE_CYAN: [
  1017.                 cyan],
  1018.             AGENT_TYPE_CYAN_LOW: [
  1019.                 light_cyan],
  1020.             AGENT_TYPE_YELLOW_LOW: [
  1021.                 light_yellow],
  1022.             AGENT_TYPE_MAGENTA_LOW: [
  1023.                 light_magenta],
  1024.             AGENT_TYPE_BLUE: [
  1025.                 blue],
  1026.             AGENT_TYPE_KCMY_CM: [
  1027.                 yellow,
  1028.                 cyan,
  1029.                 magenta],
  1030.             AGENT_TYPE_LC_LM: [
  1031.                 light_cyan,
  1032.                 light_magenta],
  1033.             AGENT_TYPE_LG_PK: [
  1034.                 light_grey,
  1035.                 dark_grey],
  1036.             AGENT_TYPE_LG: [
  1037.                 light_grey],
  1038.             AGENT_TYPE_G: [
  1039.                 dark_grey],
  1040.             AGENT_TYPE_PG: [
  1041.                 light_grey],
  1042.             AGENT_TYPE_C_M: [
  1043.                 cyan,
  1044.                 magenta],
  1045.             AGENT_TYPE_K_Y: [
  1046.                 black,
  1047.                 yellow] }
  1048.         self.supplies_headers = [
  1049.             self._DevMgr5__tr(''),
  1050.             self._DevMgr5__tr('Description'),
  1051.             self._DevMgr5__tr('HP Part No.'),
  1052.             self._DevMgr5__tr('Approx. Level'),
  1053.             self._DevMgr5__tr('Status')]
  1054.  
  1055.     
  1056.     def updateSuppliesTab(self):
  1057.         beginWaitCursor()
  1058.         flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled
  1059.         
  1060.         try:
  1061.             self.SuppliesTable.clear()
  1062.             self.SuppliesTable.setRowCount(0)
  1063.             self.SuppliesTable.setColumnCount(0)
  1064.             if self.cur_device is not None and self.cur_device.supported and self.cur_device.status_type != STATUS_TYPE_NONE and self.cur_device.device_state != DEVICE_STATE_NOT_FOUND:
  1065.                 
  1066.                 try:
  1067.                     self.cur_device.sorted_supplies
  1068.                 except AttributeError:
  1069.                     self.cur_device.sorted_supplies = []
  1070.  
  1071.                 if not self.cur_device.sorted_supplies:
  1072.                     a = 1
  1073.                     while True:
  1074.                         
  1075.                         try:
  1076.                             agent_type = int(self.cur_device.dq['agent%d-type' % a])
  1077.                             agent_kind = int(self.cur_device.dq['agent%d-kind' % a])
  1078.                         except KeyError:
  1079.                             break
  1080.  
  1081.                         self.cur_device.sorted_supplies.append((a, agent_kind, agent_type))
  1082.                         a += 1
  1083.                     self.cur_device.sorted_supplies.sort((lambda x, y: if not cmp(x[2], y[2]):
  1084. passcmp(x[1], y[1])))
  1085.                 
  1086.                 self.SuppliesTable.setRowCount(len(self.cur_device.sorted_supplies))
  1087.                 self.SuppliesTable.setColumnCount(len(self.supplies_headers))
  1088.                 self.SuppliesTable.setHorizontalHeaderLabels(self.supplies_headers)
  1089.                 self.SuppliesTable.verticalHeader().hide()
  1090.                 self.SuppliesTable.horizontalHeader().show()
  1091.                 self.SuppliesTable.setIconSize(QSize(100, 18))
  1092.                 for row, x in enumerate(self.cur_device.sorted_supplies):
  1093.                     (a, agent_kind, agent_type) = x
  1094.                     agent_level = int(self.cur_device.dq['agent%d-level' % a])
  1095.                     agent_sku = str(self.cur_device.dq['agent%d-sku' % a])
  1096.                     agent_desc = self.cur_device.dq['agent%d-desc' % a]
  1097.                     agent_health_desc = self.cur_device.dq['agent%d-health-desc' % a]
  1098.                     level_pixmap = None
  1099.                     if agent_kind in (AGENT_KIND_SUPPLY, AGENT_KIND_HEAD_AND_SUPPLY, AGENT_KIND_TONER_CARTRIDGE, AGENT_KIND_MAINT_KIT, AGENT_KIND_ADF_KIT, AGENT_KIND_INT_BATTERY, AGENT_KIND_DRUM_KIT):
  1100.                         level_pixmap = self.createStatusLevelGraphic(agent_level, agent_type)
  1101.                     
  1102.                     pixmap = None
  1103.                     if agent_kind in (AGENT_KIND_SUPPLY, AGENT_KIND_HEAD, AGENT_KIND_HEAD_AND_SUPPLY, AGENT_KIND_TONER_CARTRIDGE, AGENT_KIND_INT_BATTERY):
  1104.                         pixmap = self.getStatusIcon(agent_kind, agent_type)
  1105.                     
  1106.                     if pixmap is not None:
  1107.                         i = QTableWidgetItem(QIcon(pixmap), self._DevMgr5__tr(''))
  1108.                         i.setFlags(flags)
  1109.                         self.SuppliesTable.setItem(row, 0, i)
  1110.                     
  1111.                     for col, t in [
  1112.                         (1, agent_desc),
  1113.                         (2, agent_sku),
  1114.                         (4, agent_health_desc)]:
  1115.                         i = QTableWidgetItem(QString(t))
  1116.                         i.setFlags(flags)
  1117.                         self.SuppliesTable.setItem(row, col, i)
  1118.                     
  1119.                     if level_pixmap is not None:
  1120.                         i = QTableWidgetItem(QIcon(level_pixmap), self._DevMgr5__tr(''))
  1121.                         i.setFlags(flags)
  1122.                         self.SuppliesTable.setItem(row, 3, i)
  1123.                         continue
  1124.                 
  1125.                 self.SuppliesTable.resizeColumnsToContents()
  1126.                 self.SuppliesTable.setColumnWidth(0, 24)
  1127.                 self.SuppliesTable.setColumnWidth(3, 120)
  1128.             else:
  1129.                 log.warning('Supplies information not available for this device.')
  1130.                 flags = Qt.ItemIsEnabled
  1131.                 self.SuppliesTable.setRowCount(1)
  1132.                 self.SuppliesTable.setColumnCount(2)
  1133.                 self.SuppliesTable.setHorizontalHeaderLabels([
  1134.                     '',
  1135.                     ''])
  1136.                 self.SuppliesTable.verticalHeader().hide()
  1137.                 self.SuppliesTable.horizontalHeader().hide()
  1138.                 i = QTableWidgetItem(self._DevMgr5__tr('Supplies information not available for this device.'))
  1139.                 i.setFlags(flags)
  1140.                 self.SuppliesTable.setItem(0, 1, i)
  1141.                 pixmap = getStatusListIcon(ERROR_STATE_ERROR)[0]
  1142.                 i = QTableWidgetItem(QIcon(pixmap), self._DevMgr5__tr(''))
  1143.                 i.setFlags(flags)
  1144.                 self.SuppliesTable.setItem(0, 0, i)
  1145.                 self.SuppliesTable.resizeColumnsToContents()
  1146.                 self.SuppliesTable.setColumnWidth(0, 24)
  1147.         finally:
  1148.             endWaitCursor()
  1149.  
  1150.  
  1151.     
  1152.     def getStatusIcon(self, agent_kind, agent_type):
  1153.         if agent_kind in (AGENT_KIND_SUPPLY, AGENT_KIND_HEAD, AGENT_KIND_HEAD_AND_SUPPLY, AGENT_KIND_TONER_CARTRIDGE):
  1154.             map = self.TYPE_TO_PIX_MAP[agent_type]
  1155.             if isinstance(map, list):
  1156.                 map_len = len(map)
  1157.                 pix = QPixmap(16, 16)
  1158.                 pix.fill(QColor(0, 0, 0, 0))
  1159.                 p = QPainter()
  1160.                 p.begin(pix)
  1161.                 p.setRenderHint(QPainter.Antialiasing)
  1162.                 if map_len == 1:
  1163.                     p.setPen(QColor(map[0]))
  1164.                     p.setBrush(QBrush(QColor(map[0]), Qt.SolidPattern))
  1165.                     p.drawPie(2, 2, 10, 10, 0, 5760)
  1166.                 elif map_len == 2:
  1167.                     p.setPen(QColor(map[0]))
  1168.                     p.setBrush(QBrush(QColor(map[0]), Qt.SolidPattern))
  1169.                     p.drawPie(2, 4, 8, 8, 0, 5760)
  1170.                     p.setPen(QColor(map[1]))
  1171.                     p.setBrush(QBrush(QColor(map[1]), Qt.SolidPattern))
  1172.                     p.drawPie(6, 4, 8, 8, 0, 5760)
  1173.                 elif map_len == 3:
  1174.                     p.setPen(QColor(map[2]))
  1175.                     p.setBrush(QBrush(QColor(map[2]), Qt.SolidPattern))
  1176.                     p.drawPie(6, 6, 8, 8, 0, 5760)
  1177.                     p.setPen(QColor(map[1]))
  1178.                     p.setBrush(QBrush(QColor(map[1]), Qt.SolidPattern))
  1179.                     p.drawPie(2, 6, 8, 8, 0, 5760)
  1180.                     p.setPen(QColor(map[0]))
  1181.                     p.setBrush(QBrush(QColor(map[0]), Qt.SolidPattern))
  1182.                     p.drawPie(4, 2, 8, 8, 0, 5760)
  1183.                 
  1184.                 p.end()
  1185.                 return pix
  1186.             return map
  1187.         agent_kind in (AGENT_KIND_SUPPLY, AGENT_KIND_HEAD, AGENT_KIND_HEAD_AND_SUPPLY, AGENT_KIND_TONER_CARTRIDGE)
  1188.         if agent_kind == AGENT_KIND_INT_BATTERY:
  1189.             return self.pix_battery
  1190.  
  1191.     
  1192.     def createStatusLevelGraphic(self, percent, agent_type, w = 100, h = 18):
  1193.         if percent:
  1194.             fw = (w / 100) * percent
  1195.         else:
  1196.             fw = 0
  1197.         px = QPixmap(w, h)
  1198.         px.fill(QColor(0, 0, 0, 0))
  1199.         pp = QPainter()
  1200.         pp.begin(px)
  1201.         pp.setRenderHint(QPainter.Antialiasing)
  1202.         pp.setPen(Qt.black)
  1203.         map = self.TYPE_TO_PIX_MAP[agent_type]
  1204.         map_len = len(map)
  1205.         if map_len == 1 or map_len > 3:
  1206.             pp.fillRect(0, 0, fw, h, QBrush(QColor(map[0])))
  1207.         elif map_len == 2:
  1208.             h2 = h / 2
  1209.             pp.fillRect(0, 0, fw, h2, QBrush(QColor(map[0])))
  1210.             pp.fillRect(0, h2, fw, h, QBrush(QColor(map[1])))
  1211.         elif map_len == 3:
  1212.             h3 = h / 3
  1213.             h23 = 2 * h3
  1214.             pp.fillRect(0, 0, fw, h3, QBrush(QColor(map[0])))
  1215.             pp.fillRect(0, h3, fw, h23, QBrush(QColor(map[1])))
  1216.             pp.fillRect(0, h23, fw, h, QBrush(QColor(map[2])))
  1217.         
  1218.         pp.drawRect(0, 0, w, h)
  1219.         if percent > 75 and agent_type in (AGENT_TYPE_BLACK, AGENT_TYPE_UNSPECIFIED, AGENT_TYPE_BLUE):
  1220.             pp.setPen(Qt.white)
  1221.         
  1222.         w1 = 3 * w / 4
  1223.         h6 = h / 6
  1224.         pp.drawLine(w1, 0, w1, h6)
  1225.         pp.drawLine(w1, h, w1, h - h6)
  1226.         if percent > 50 and agent_type in (AGENT_TYPE_BLACK, AGENT_TYPE_UNSPECIFIED, AGENT_TYPE_BLUE):
  1227.             pp.setPen(Qt.white)
  1228.         
  1229.         w2 = w / 2
  1230.         h4 = h / 4
  1231.         pp.drawLine(w2, 0, w2, h4)
  1232.         pp.drawLine(w2, h, w2, h - h4)
  1233.         if percent > 25 and agent_type in (AGENT_TYPE_BLACK, AGENT_TYPE_UNSPECIFIED, AGENT_TYPE_BLUE):
  1234.             pp.setPen(Qt.white)
  1235.         
  1236.         w4 = w / 4
  1237.         pp.drawLine(w4, 0, w4, h6)
  1238.         pp.drawLine(w4, h, w4, h - h6)
  1239.         pp.end()
  1240.         return px
  1241.  
  1242.     
  1243.     def initPrintSettingsTab(self):
  1244.         pass
  1245.  
  1246.     
  1247.     def updatePrintSettingsTab(self):
  1248.         beginWaitCursor()
  1249.         
  1250.         try:
  1251.             if self.cur_device.device_type == DEVICE_TYPE_PRINTER:
  1252.                 self.PrintSettingsPrinterNameLabel.setText(self._DevMgr5__tr('Printer Name:'))
  1253.             else:
  1254.                 self.PrintSettingsPrinterNameLabel.setText(self._DevMgr5__tr('Fax Name:'))
  1255.             self.PrintSettingsToolbox.updateUi(self.cur_device, self.cur_printer)
  1256.         finally:
  1257.             endWaitCursor()
  1258.  
  1259.  
  1260.     
  1261.     def initPrintControlTab(self):
  1262.         self.JOB_STATES = {
  1263.             cups.IPP_JOB_PENDING: self._DevMgr5__tr('Pending'),
  1264.             cups.IPP_JOB_HELD: self._DevMgr5__tr('On hold'),
  1265.             cups.IPP_JOB_PROCESSING: self._DevMgr5__tr('Printing'),
  1266.             cups.IPP_JOB_STOPPED: self._DevMgr5__tr('Stopped'),
  1267.             cups.IPP_JOB_CANCELLED: self._DevMgr5__tr('Canceled'),
  1268.             cups.IPP_JOB_ABORTED: self._DevMgr5__tr('Aborted'),
  1269.             cups.IPP_JOB_COMPLETED: self._DevMgr5__tr('Completed') }
  1270.         self.CancelJobButton.setIcon(QIcon(load_pixmap('cancel', '16x16')))
  1271.         self.RefreshButton.setIcon(QIcon(load_pixmap('refresh', '16x16')))
  1272.         self.JOB_STATE_ICONS = {
  1273.             cups.IPP_JOB_PENDING: QIcon(load_pixmap('busy', '16x16')),
  1274.             cups.IPP_JOB_HELD: QIcon(load_pixmap('busy', '16x16')),
  1275.             cups.IPP_JOB_PROCESSING: QIcon(load_pixmap('print', '16x16')),
  1276.             cups.IPP_JOB_STOPPED: QIcon(load_pixmap('warning', '16x16')),
  1277.             cups.IPP_JOB_CANCELLED: QIcon(load_pixmap('warning', '16x16')),
  1278.             cups.IPP_JOB_ABORTED: QIcon(load_pixmap('error', '16x16')),
  1279.             cups.IPP_JOB_COMPLETED: QIcon(load_pixmap('ok', '16x16')) }
  1280.         self.connect(self.StartStopButton, SIGNAL('clicked()'), self.StartStopButton_clicked)
  1281.         self.connect(self.AcceptRejectButton, SIGNAL('clicked()'), self.AcceptRejectButton_clicked)
  1282.         self.connect(self.SetDefaultButton, SIGNAL('clicked()'), self.SetDefaultButton_clicked)
  1283.         self.connect(self.CancelJobButton, SIGNAL('clicked()'), self.CancelJobButton_clicked)
  1284.         self.connect(self.RefreshButton, SIGNAL('clicked()'), self.RefreshButton_clicked)
  1285.         self.job_headers = [
  1286.             self._DevMgr5__tr('Status'),
  1287.             self._DevMgr5__tr('Title/Description'),
  1288.             self._DevMgr5__tr('Job ID')]
  1289.  
  1290.     
  1291.     def CancelJobButton_clicked(self):
  1292.         item = self.JobTable.currentItem()
  1293.         if item is not None:
  1294.             (job_id, ok) = item.data(Qt.UserRole).toInt()
  1295.             if ok and job_id:
  1296.                 self.cur_device.cancelJob(job_id)
  1297.                 QTimer.singleShot(1000, self.updatePrintControlTab)
  1298.             
  1299.         
  1300.  
  1301.     
  1302.     def RefreshButton_clicked(self):
  1303.         self.updatePrintControlTab()
  1304.  
  1305.     
  1306.     def updatePrintControlTab(self):
  1307.         if self.cur_device.device_type == DEVICE_TYPE_PRINTER:
  1308.             self.PrintControlPrinterNameLabel.setText(self._DevMgr5__tr('Printer Name:'))
  1309.         else:
  1310.             self.PrintControlPrinterNameLabel.setText(self._DevMgr5__tr('Fax Name:'))
  1311.         self.JobTable.clear()
  1312.         self.JobTable.setRowCount(0)
  1313.         self.JobTable.setColumnCount(0)
  1314.         self.updatePrintController()
  1315.         flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled
  1316.         jobs = cups.getJobs()
  1317.         num_jobs = 0
  1318.         for j in jobs:
  1319.             if j.dest.decode('utf-8') == unicode(self.cur_printer):
  1320.                 num_jobs += 1
  1321.                 continue
  1322.         
  1323.         if num_jobs:
  1324.             self.CancelJobButton.setEnabled(True)
  1325.             self.JobTable.setRowCount(num_jobs)
  1326.             self.JobTable.setColumnCount(len(self.job_headers))
  1327.             self.JobTable.setHorizontalHeaderLabels(self.job_headers)
  1328.             for row, j in enumerate(jobs):
  1329.                 if j.dest.decode('utf-8') == unicode(self.cur_printer):
  1330.                     i = QTableWidgetItem(self.JOB_STATE_ICONS[j.state], self.JOB_STATES[j.state])
  1331.                     i.setData(Qt.UserRole, QVariant(j.id))
  1332.                     i.setFlags(flags)
  1333.                     self.JobTable.setItem(row, 0, i)
  1334.                     i = QTableWidgetItem(j.title)
  1335.                     i.setFlags(flags)
  1336.                     self.JobTable.setItem(row, 1, i)
  1337.                     i = QTableWidgetItem(unicode(j.id))
  1338.                     i.setFlags(flags)
  1339.                     self.JobTable.setItem(row, 2, i)
  1340.                     continue
  1341.             
  1342.             self.JobTable.setCurrentCell(0, 0)
  1343.             self.JobTable.resizeColumnsToContents()
  1344.         else:
  1345.             self.CancelJobButton.setEnabled(False)
  1346.  
  1347.     
  1348.     def getPrinterState(self):
  1349.         self.printer_state = cups.IPP_PRINTER_STATE_IDLE
  1350.         self.printer_accepting = True
  1351.         cups_printers = cups.getPrinters()
  1352.         for p in cups_printers:
  1353.             if p.name.decode('utf-8') == self.cur_printer:
  1354.                 self.printer_state = p.state
  1355.                 self.printer_accepting = p.accepting
  1356.                 break
  1357.                 continue
  1358.         
  1359.  
  1360.     
  1361.     def updatePrintController(self):
  1362.         self.SetDefaultButton.setText(self._DevMgr5__tr('Set as Default'))
  1363.         default_printer = cups.getDefaultPrinter()
  1364.         if default_printer is not None:
  1365.             default_printer = default_printer.decode('utf8')
  1366.         
  1367.         if default_printer == self.cur_printer:
  1368.             self.SetDefaultLabel.setText(self._DevMgr5__tr('Default Printer'))
  1369.             self.SetDefaultIcon.setPixmap(load_pixmap('ok', '16x16'))
  1370.             self.SetDefaultButton.setEnabled(False)
  1371.         else:
  1372.             self.SetDefaultLabel.setText(self._DevMgr5__tr('Not Default Printer'))
  1373.             self.SetDefaultIcon.setPixmap(load_pixmap('info', '16x16'))
  1374.             self.SetDefaultButton.setEnabled(True)
  1375.         self.getPrinterState()
  1376.         if self.printer_state == cups.IPP_PRINTER_STATE_IDLE:
  1377.             self.StartStopLabel.setText(self._DevMgr5__tr('Started/Idle'))
  1378.             self.StartStopIcon.setPixmap(load_pixmap('idle', '16x16'))
  1379.             if self.cur_device.device_type == DEVICE_TYPE_PRINTER:
  1380.                 self.StartStopButton.setText(self._DevMgr5__tr('Stop Printer'))
  1381.             else:
  1382.                 self.StartStopButton.setText(self._DevMgr5__tr('Stop Fax'))
  1383.         elif self.printer_state == cups.IPP_PRINTER_STATE_PROCESSING:
  1384.             self.StartStopLabel.setText(self._DevMgr5__tr('Started/Processing'))
  1385.             self.StartStopIcon.setPixmap(load_pixmap('busy', '16x16'))
  1386.             if self.cur_device.device_type == DEVICE_TYPE_PRINTER:
  1387.                 self.StartStopButton.setText(self._DevMgr5__tr('Stop Printer'))
  1388.             else:
  1389.                 self.StartStopButton.setText(self._DevMgr5__tr('Stop Fax'))
  1390.         else:
  1391.             self.StartStopLabel.setText(self._DevMgr5__tr('Stopped'))
  1392.             self.StartStopIcon.setPixmap(load_pixmap('warning', '16x16'))
  1393.             if self.cur_device.device_type == DEVICE_TYPE_PRINTER:
  1394.                 self.StartStopButton.setText(self._DevMgr5__tr('Start Printer'))
  1395.             else:
  1396.                 self.StartStopButton.setText(self._DevMgr5__tr('Start Fax'))
  1397.         if self.printer_accepting:
  1398.             self.AcceptRejectLabel.setText(self._DevMgr5__tr('Accepting Jobs'))
  1399.             self.AcceptRejectIcon.setPixmap(load_pixmap('idle', '16x16'))
  1400.             self.AcceptRejectButton.setText(self._DevMgr5__tr('Reject Jobs'))
  1401.         else:
  1402.             self.AcceptRejectLabel.setText(self._DevMgr5__tr('Rejecting Jobs'))
  1403.             self.AcceptRejectIcon.setPixmap(load_pixmap('warning', '16x16'))
  1404.             self.AcceptRejectButton.setText(self._DevMgr5__tr('Accept Jobs'))
  1405.  
  1406.     
  1407.     def StartStopButton_clicked(self):
  1408.         beginWaitCursor()
  1409.         
  1410.         try:
  1411.             if self.printer_state in (cups.IPP_PRINTER_STATE_IDLE, cups.IPP_PRINTER_STATE_PROCESSING):
  1412.                 result = cups.stop(self.cur_printer)
  1413.                 if result:
  1414.                     if self.cur_device.device_type == DEVICE_TYPE_PRINTER:
  1415.                         e = EVENT_PRINTER_QUEUE_STOPPED
  1416.                     else:
  1417.                         e = EVENT_FAX_QUEUE_STOPPED
  1418.                 
  1419.             else:
  1420.                 result = cups.start(self.cur_printer)
  1421.                 if result:
  1422.                     if self.cur_device.device_type == DEVICE_TYPE_PRINTER:
  1423.                         e = EVENT_PRINTER_QUEUE_STARTED
  1424.                     else:
  1425.                         e = EVENT_FAX_QUEUE_STARTED
  1426.                 
  1427.             if result:
  1428.                 self.updatePrintController()
  1429.                 self.cur_device.sendEvent(e, self.cur_printer)
  1430.             else:
  1431.                 log.error('Start/Stop printer operation failed')
  1432.         finally:
  1433.             endWaitCursor()
  1434.  
  1435.  
  1436.     
  1437.     def AcceptRejectButton_clicked(self):
  1438.         beginWaitCursor()
  1439.         
  1440.         try:
  1441.             if self.printer_accepting:
  1442.                 result = cups.reject(self.cur_printer)
  1443.                 if result:
  1444.                     if self.cur_device.device_type == DEVICE_TYPE_PRINTER:
  1445.                         e = EVENT_PRINTER_QUEUE_REJECTING_JOBS
  1446.                     else:
  1447.                         e = EVENT_FAX_QUEUE_REJECTING_JOBS
  1448.                 
  1449.             else:
  1450.                 result = cups.accept(self.cur_printer)
  1451.                 if result:
  1452.                     if self.cur_device.device_type == DEVICE_TYPE_PRINTER:
  1453.                         e = EVENT_PRINTER_QUEUE_ACCEPTING_JOBS
  1454.                     else:
  1455.                         e = EVENT_FAX_QUEUE_ACCEPTING_JOBS
  1456.                 
  1457.             if result:
  1458.                 self.updatePrintController()
  1459.                 self.cur_device.sendEvent(e, self.cur_printer)
  1460.             else:
  1461.                 log.error('Reject/Accept jobs operation failed')
  1462.         finally:
  1463.             endWaitCursor()
  1464.  
  1465.  
  1466.     
  1467.     def SetDefaultButton_clicked(self):
  1468.         beginWaitCursor()
  1469.         
  1470.         try:
  1471.             result = cups.setDefaultPrinter(self.cur_printer.encode('utf8'))
  1472.             if not result:
  1473.                 log.error('Set default printer failed.')
  1474.             else:
  1475.                 self.updatePrintController()
  1476.                 if self.cur_device.device_type == DEVICE_TYPE_PRINTER:
  1477.                     e = EVENT_PRINTER_QUEUE_SET_AS_DEFAULT
  1478.                 else:
  1479.                     e = EVENT_FAX_QUEUE_SET_AS_DEFAULT
  1480.                 self.cur_device.sendEvent(e, self.cur_printer)
  1481.         finally:
  1482.             endWaitCursor()
  1483.  
  1484.  
  1485.     
  1486.     def cancelCheckedJobs(self):
  1487.         beginWaitCursor()
  1488.         
  1489.         try:
  1490.             item = self.JobTable.firstChild()
  1491.             while item is not None:
  1492.                 if item.isOn():
  1493.                     self.cur_device.cancelJob(item.job_id)
  1494.                 
  1495.                 item = item.nextSibling()
  1496.         finally:
  1497.             endWaitCursor()
  1498.  
  1499.         self.updatePrintControlTab()
  1500.  
  1501.     
  1502.     def closeEvent(self, event):
  1503.         self.cleanup()
  1504.         event.accept()
  1505.  
  1506.     
  1507.     def cleanup(self):
  1508.         self.cleanupChildren()
  1509.  
  1510.     
  1511.     def cleanupChildren(self):
  1512.         log.debug('Cleaning up child processes.')
  1513.         
  1514.         try:
  1515.             os.waitpid(-1, os.WNOHANG)
  1516.         except OSError:
  1517.             pass
  1518.  
  1519.  
  1520.     
  1521.     def quit(self):
  1522.         self.cleanupChildren()
  1523.         self.close()
  1524.  
  1525.     
  1526.     def PreferencesAction_activated(self, tab_to_show = 0):
  1527.         dlg = SettingsDialog(self)
  1528.         dlg.TabWidget.setCurrentIndex(tab_to_show)
  1529.         if dlg.exec_() == QDialog.Accepted:
  1530.             self.user_settings.load()
  1531.             self.cur_device.sendEvent(EVENT_USER_CONFIGURATION_CHANGED, self.cur_printer)
  1532.         
  1533.  
  1534.     
  1535.     def SetupDeviceAction_activated(self):
  1536.         su_sudo_str = su_sudo()
  1537.         if su_sudo_str is None:
  1538.             QMessageBox.critical(self, self.windowTitle(), self._DevMgr5__tr('<b>Unable to find an appropriate su/sudo utility to run hp-setup.</b>'), QMessageBox.Ok, QMessageBox.NoButton, QMessageBox.NoButton)
  1539.         elif utils.which('hp-setup'):
  1540.             cmd = su_sudo_str % 'hp-setup -u'
  1541.         else:
  1542.             cmd = su_sudo_str % 'python ./setup.py -u'
  1543.         log.debug(cmd)
  1544.         utils.run(cmd, log_output = True, password_func = None, timeout = 1)
  1545.         self.rescanDevices()
  1546.  
  1547.     
  1548.     def RemoveDeviceAction_activated(self):
  1549.         if self.cur_device is not None:
  1550.             x = QMessageBox.critical(self, self.windowTitle(), self._DevMgr5__tr('<b>Annoying Confirmation: Are you sure you want to remove this device?</b>'), QMessageBox.Yes, QMessageBox.No | QMessageBox.Default, QMessageBox.NoButton)
  1551.             if x == QMessageBox.Yes:
  1552.                 beginWaitCursor()
  1553.                 print_uri = self.cur_device.device_uri
  1554.                 fax_uri = print_uri.replace('hp:', 'hpfax:')
  1555.                 log.debug(print_uri)
  1556.                 log.debug(fax_uri)
  1557.                 self.cups_devices = device.getSupportedCUPSDevices([
  1558.                     'hp',
  1559.                     'hpfax'])
  1560.                 for d in self.cups_devices:
  1561.                     if d in (print_uri, fax_uri):
  1562.                         for p in self.cups_devices[d]:
  1563.                             log.debug('Removing %s' % p)
  1564.                             cups.delPrinter(p)
  1565.                         
  1566.                 
  1567.                 self.cur_device = None
  1568.                 self.cur_device_uri = ''
  1569.                 user_conf.set('last_used', 'device_uri', '')
  1570.                 endWaitCursor()
  1571.                 self.rescanDevices()
  1572.             
  1573.         
  1574.  
  1575.     
  1576.     def runExternalCommand(self, cmd, macro_char = '%'):
  1577.         beginWaitCursor()
  1578.         
  1579.         try:
  1580.             if len(cmd) == 0:
  1581.                 FailureUI(self._DevMgr5__tr('<p><b>Unable to run command. No command specified.</b><p>Use <pre>Configure...</pre> to specify a command to run.'))
  1582.                 log.error('No command specified. Use settings to configure commands.')
  1583.             else:
  1584.                 log.debug('Run: %s %s (%s) %s' % ('********************', cmd, self.cur_device_uri, '********************'))
  1585.                 log.debug(cmd)
  1586.                 
  1587.                 try:
  1588.                     cmd = []([ self.cur_device.device_vars.get(x, x) for x in cmd.split(macro_char) ])
  1589.                 except AttributeError:
  1590.                     pass
  1591.  
  1592.                 log.debug(cmd)
  1593.                 path = cmd.split()[0]
  1594.                 args = cmd.split()
  1595.                 log.debug(path)
  1596.                 log.debug(args)
  1597.                 self.cleanupChildren()
  1598.                 os.spawnvp(os.P_NOWAIT, path, args)
  1599.                 qApp.processEvents()
  1600.         finally:
  1601.             endWaitCursor()
  1602.  
  1603.  
  1604.     
  1605.     def helpContents(self):
  1606.         utils.openURL(self.docs)
  1607.  
  1608.     
  1609.     def helpAbout(self):
  1610.         dlg = AboutDialog(self, prop.version, self.toolbox_version + ' (Qt4)')
  1611.         dlg.exec_()
  1612.  
  1613.     
  1614.     def __tr(self, s, c = None):
  1615.         return qApp.translate('DevMgr5', s, c)
  1616.  
  1617.  
  1618.  
  1619. class PasswordDialog(QDialog):
  1620.     
  1621.     def __init__(self, prompt, parent = None, name = None, modal = 0, fl = 0):
  1622.         log.debug('PasswordDialog')
  1623.         QDialog.__init__(self)
  1624.         if not name:
  1625.             self.setObjectName('PasswordDialog')
  1626.         
  1627.         passwordDlg_baseLayout = QGridLayout(self)
  1628.         passwordDlg_baseLayout.setMargin(11)
  1629.         passwordDlg_baseLayout.setSpacing(6)
  1630.         passwordDlg_baseLayout.setObjectName('passwordDlg_baseLayout')
  1631.         self.promptTextLabel = QLabel(self)
  1632.         self.promptTextLabel.setObjectName('promptTextLabel')
  1633.         self.promptTextLabel.setText(prompt)
  1634.         passwordDlg_baseLayout.addWidget(self.promptTextLabel, 0, 0)
  1635.         self.passwordLineEdit = QLineEdit(self)
  1636.         self.passwordLineEdit.setObjectName('passwordLineEdit')
  1637.         self.passwordLineEdit.setEchoMode(QLineEdit.Password)
  1638.         passwordDlg_baseLayout.addWidget(self.passwordLineEdit, 1, 0, 1, 2)
  1639.         spacer1 = QSpacerItem(20, 61, QSizePolicy.Minimum, QSizePolicy.Expanding)
  1640.         passwordDlg_baseLayout.addItem(spacer1, 2, 0)
  1641.         spacer2 = QSpacerItem(321, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  1642.         passwordDlg_baseLayout.addItem(spacer2, 3, 0)
  1643.         self.okPushButton = QPushButton(self)
  1644.         self.okPushButton.setObjectName('okPushButton')
  1645.         passwordDlg_baseLayout.addWidget(self.okPushButton, 3, 1)
  1646.         self.languageChange()
  1647.         self.resize(QSize(420, 163).expandedTo(self.minimumSizeHint()))
  1648.         self.connect(self.okPushButton, SIGNAL('clicked()'), self.accept)
  1649.         self.connect(self.passwordLineEdit, SIGNAL('returnPressed()'), self.accept)
  1650.  
  1651.     
  1652.     def getPassword(self):
  1653.         return unicode(self.passwordLineEdit.text())
  1654.  
  1655.     
  1656.     def languageChange(self):
  1657.         self.setWindowTitle(self._PasswordDialog__tr('HP Device Manager - Enter Password'))
  1658.         self.okPushButton.setText(self._PasswordDialog__tr('OK'))
  1659.  
  1660.     
  1661.     def __tr(self, s, c = None):
  1662.         return qApp.translate('PasswordDialog', s, c)
  1663.  
  1664.  
  1665.  
  1666. def showPasswordUI(prompt):
  1667.     
  1668.     try:
  1669.         dlg = PasswordDialog(prompt, None)
  1670.         if dlg.exec_() == QDialog.Accepted:
  1671.             return dlg.getPassword()
  1672.     finally:
  1673.         pass
  1674.  
  1675.     return ''
  1676.  
  1677.